﻿using Garfield.Core.Runtime;

namespace Garfield.Core.Test
{
    class TestPlugin : Plugin
    {
        protected override void Initialize()
        {
        }
    }

    [Plugin("PluginId")]
    class PluginId : TestPlugin { }
    class DefaultPluginId : TestPlugin { }

    [PluginDependencies("DependencyA", "DependencyB")]
    class PluginIdentifierDependencies : TestPlugin { }

    [PluginDependencies(typeof(PluginId), typeof(DefaultPluginId))]
    class PluginTypeDependencies : TestPlugin { }
    class InheritedDependencies : PluginTypeDependencies { }

    [PluginDependencies(typeof(string))]
    class DependsOnNonPlugin : TestPlugin { }
    [PluginDependencies(typeof(Plugin))]
    class DependsOnAbstractPlugin : TestPlugin { }

    class ExtensionPointDeclaration : TestPlugin
    {
        public static readonly ExtensionPoint<string> StringExtensionPoint =
            DeclareExtensionPoint<string>(typeof(ExtensionPointDeclaration), "StringExtensionPoint", false);

        public static readonly ExtensionPoint<string, string> StringNamedExtensionPoint =
            DeclareExtensionPoint<string, string>(typeof(ExtensionPointDeclaration), "StringNamedExtensionPoint", false);

        public static readonly ExtensionPoint<object> ObjectExtensionPoint =
            DeclareExtensionPoint<object>(typeof(ExtensionPointDeclaration), "ObjectExtensionPoint", false);

        public static readonly ExtensionPoint<string, object> ObjectNamedExtensionPoint =
            DeclareExtensionPoint<string, object>(typeof(ExtensionPointDeclaration), "ObjectNamedExtensionPoint", false);
    }

    class ExtensionPointADeclaration : TestPlugin
    {
        public static readonly ExtensionPoint<string> ExtensionPointA =
           DeclareExtensionPoint<string>(typeof(ExtensionPointDeclaration), "ExtensionPointA", false);
    }

    class Extender : TestPlugin
    {
        protected override void Initialize()
        {
            Register(ExtensionPointDeclaration.StringExtensionPoint, "value");
            Register(ExtensionPointDeclaration.ObjectExtensionPoint, Implementation<string>());
            Register(ExtensionPointDeclaration.StringNamedExtensionPoint, "identifier", "value");
            Register(ExtensionPointDeclaration.ObjectNamedExtensionPoint, "identifier", Implementation<string>());
        }
    }

    class SelfDepended : TestPlugin
    {
        public static readonly ExtensionPoint<string> StringExtensionPoint =
            DeclareExtensionPoint<string>(typeof(SelfDepended), "StringExtensionPoint", false);

        protected override void Initialize()
        {
            Register(StringExtensionPoint, "value");            
        }
    }

    [PluginDependencies(typeof(DirectCyclicDependedB))]
    class DirectCyclicDependedA : TestPlugin{}
    [PluginDependencies(typeof(DirectCyclicDependedA))]
    class DirectCyclicDependedB : TestPlugin {}

    [PluginDependencies(typeof(IndirectCyclicDependedB))]
    class IndirectCyclicDependedA : TestPlugin { }
    [PluginDependencies(typeof(IndirectCyclicDependedC))]
    class IndirectCyclicDependedB : TestPlugin { }
    [PluginDependencies(typeof(IndirectCyclicDependedA))]
    class IndirectCyclicDependedC : TestPlugin { }

    class StartableDependency : TestPlugin
    {
        public int StartCount { get; private set; }
        public override void Start(IServiceLocator serviceLocator)
        {
            StartCount++;
        }
    }

    [PluginDependencies(typeof(StartableDependency))]
    class StartableDependencyConsumer : TestPlugin {}
}
